﻿using System.Linq;
using System.Xml.Linq;
using SharePhone.Common;
using SharePhone.Common.List;
using SharePhone.Core;

namespace SharePhone.Provider.WebServices
{
    public delegate void GetListCompletedHandler(object sender, RequestCompleteEventArgs e);

    public delegate void GetListCollectionCompletedHandler(object sender, RequestCompleteEventArgs e);

    public delegate void GetListItemsCompletedHandler(object sender, RequestCompleteEventArgs e);

    public delegate void UpdateListItemsCompletedHandler(object sender, RequestCompleteEventArgs e);

    public class SPListService : BaseWebService
    {
        private const string URL = "/_vti_bin/Lists.asmx";
        private const string ActionGetList = "http://schemas.microsoft.com/sharepoint/soap/GetList";
        private const string ActionUpdateListItems = "http://schemas.microsoft.com/sharepoint/soap/UpdateListItems";
        private const string ActionGetListItems = "http://schemas.microsoft.com/sharepoint/soap/GetListItems";
        private const string ActionGetListCollection = "http://schemas.microsoft.com/sharepoint/soap/GetListCollection";
        private const string ActionGetContentTypes = "http://schemas.microsoft.com/sharepoint/soap/GetListContentTypes";
        private const string ActionGetContentType = "http://schemas.microsoft.com/sharepoint/soap/GetListContentType";

        private const string SoapGetList =
            @"<GetList xmlns='http://schemas.microsoft.com/sharepoint/soap/' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'><listName>{0}</listName></GetList>";

        private const string SoapUpdateListItems =
            @"<UpdateListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'><listName>{0}</listName><updates>{1}</updates></UpdateListItems>";

        private const string SoapGetListItems =
            @"<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'><listName>{0}</listName><viewName/><query>{1}</query><viewFields>{2}</viewFields><rowLimit>{3}</rowLimit><queryOptions>{4}</queryOptions><webID/></GetListItems>";

        private const string SoapGetListCollection =
            @"<GetListCollection xmlns='http://schemas.microsoft.com/sharepoint/soap/' />";

        private const string SoapGetContentTypes =
            @"<GetListContentTypes xmlns='http://schemas.microsoft.com/sharepoint/soap/'><listName>{0}</listName><contentTypeId>{1}</contentTypeId></GetListContentTypes>";

        private const string SoapGetContentType =
            @"<GetListContentType xmlns='http://schemas.microsoft.com/sharepoint/soap/'><listName>{0}</listName><contentTypeId>{1}</contentTypeId></GetListContentType>";

        private readonly CredentialSettings credentials;

        public SPListService(string baseUrl, CredentialSettings credentials)
        {
            BaseUrl = baseUrl;
            this.credentials = credentials;
        }

        public event GetListCompletedHandler GetListCompleted;
        public event GetListCollectionCompletedHandler GetListCollectionCompleted;
        public event GetListItemsCompletedHandler GetListItemsCompleted;
        public event UpdateListItemsCompletedHandler UpdateListItemsCompleted;

        internal override string GetUrl()
        {
            return BaseUrl + URL;
        }

        public void GetListAsync<T>(string listName) where T : BaseItem
        {
            GetResponse(ActionGetList, string.Format(SoapGetList, listName), GetNetworkCredential(credentials),
                        (object sender, RequestCompleteEventArgs e) =>
                            {
                                XElement list =
                                    e.Result.Descendants(XName.Get("List",
                                                                   "http://schemas.microsoft.com/sharepoint/soap/")).
                                        FirstOrDefault();
                                OnGetListCompleted(list);
                            });
        }

        //public XElement GetContentTypes(string listName, string contentTypeId) {
        //    string ctId = (string.IsNullOrEmpty(contentTypeId)?string.Empty:contentTypeId);
        //    XDocument doc = GetResponse(ActionGetContentTypes, string.Format(SoapGetContentTypes, listName, ctId), GetNetworkCredential(credentials));
        //    var result = doc.Descendants(XName.Get("ContentTypes", "http://schemas.microsoft.com/sharepoint/soap/")).FirstOrDefault();
        //    return result;
        //}
        //public XElement GetContentType(string listName, string contentTypeId) {
        //    string ctId = (string.IsNullOrEmpty(contentTypeId) ? string.Empty : contentTypeId);
        //    XDocument doc = GetResponse(ActionGetContentType, string.Format(SoapGetContentType, listName, ctId), GetNetworkCredential(credentials));
        //    var result = doc.Descendants(XName.Get("ContentType", "http://schemas.microsoft.com/sharepoint/soap/")).FirstOrDefault();
        //    return result;
        //}
        public void GetListCollectionAsync()
        {
            GetResponse(ActionGetListCollection, SoapGetListCollection, GetNetworkCredential(credentials),
                        (object sender, RequestCompleteEventArgs e) =>
                            {
                                XElement result =
                                    e.Result.Descendants(XName.Get("Lists",
                                                                   "http://schemas.microsoft.com/sharepoint/soap/")).
                                        FirstOrDefault();
                                OnGetListCollectionCompleted(result);
                            });
        }

        public void UpdateListItemsAsync(string listName, XElement batchUpdate)
        {
            GetResponse(ActionUpdateListItems, string.Format(SoapUpdateListItems, listName, batchUpdate),
                        GetNetworkCredential(credentials), (object sender, RequestCompleteEventArgs e) =>
                                                               {
                                                                   XElement result =
                                                                       e.Result.Descendants(XName.Get("Results",
                                                                                                      "http://schemas.microsoft.com/sharepoint/soap/"))
                                                                           .FirstOrDefault();
                                                                   OnUpdateListItemsCompleted(result);
                                                               });
        }

        public void GetListItemsAsync<T>(SPList<T> list, XElement query, XElement viewFields, int rowLimit,
                                         XElement queryOptions) where T : BaseItem, new()
        {
            GetResponse(ActionGetListItems,
                        string.Format(SoapGetListItems, list.Title, query, viewFields,
                                      (rowLimit == 0 ? string.Empty : rowLimit.ToString()), queryOptions),
                        GetNetworkCredential(credentials), (object sender, RequestCompleteEventArgs e) =>
                                                               {
                                                                   XElement result =
                                                                       e.Result.Descendants(XName.Get("listitems",
                                                                                                      "http://schemas.microsoft.com/sharepoint/soap/"))
                                                                           .FirstOrDefault();
                                                                   OnGetListItemsCompleted(result);
                                                               });
        }

        protected void OnGetListCompleted(XElement result)
        {
            if (GetListCompleted != null)
                GetListCompleted(this, new RequestCompleteEventArgs(result));
        }

        protected void OnGetListCollectionCompleted(XElement result)
        {
            if (GetListCollectionCompleted != null)
                GetListCollectionCompleted(this, new RequestCompleteEventArgs(result));
        }

        protected void OnGetListItemsCompleted(XElement result)
        {
            if (GetListItemsCompleted != null)
                GetListItemsCompleted(this, new RequestCompleteEventArgs(result));
        }

        protected void OnUpdateListItemsCompleted(XElement result)
        {
            if (UpdateListItemsCompleted != null)
                UpdateListItemsCompleted(this, new RequestCompleteEventArgs(result));
        }
    }
}